﻿using System;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace com.hyrentals.webcommon.extensions
{
    public static class PartialViewExtensions
    {
        /// <summary>Renders a view to string.</summary> 
        public static string RenderPartialToString(this HtmlHelper html, string viewName, object viewData)
        {
            return RenderViewToString(html.ViewContext.Controller.ControllerContext, viewName, viewData, null);
        }
        /// <summary>Renders a view to string.</summary> 
        public static string RenderPartialViewToString(this Controller controller, string viewName, object viewData)
        {
            return RenderViewToString(controller.ControllerContext, viewName, viewData, null);
        }

        /// <summary>Renders a view to string.</summary> 
        public static string RenderPartialViewToString(this Controller controller, string viewName, object viewData, ViewDataDictionary viewDic)
        {
            return RenderViewToString(controller.ControllerContext, viewName, viewData, viewDic);
        }

        /// <summary>Renders a view to string.</summary> 
        public static string RenderPartialViewToString(this Controller controller, string viewName, ViewDataDictionary viewDic)
        {
            return RenderViewToString(controller.ControllerContext, viewName, null, viewDic);
        }

        private static string RenderViewToString(ControllerContext context,
                                                string viewName, object model, ViewDataDictionary viewDic)
        {
            //Create memory writer 
            StringBuilder sb = new StringBuilder();
            StringWriter memWriter = new StringWriter(sb);

            //Create fake http context to render the view 
            HttpResponse fakeResponse = new HttpResponse(memWriter);
            HttpContext fakeContext = new HttpContext(HttpContext.Current.Request, fakeResponse);
            ControllerContext fakeControllerContext = new ControllerContext(
                new HttpContextWrapper(fakeContext),
                context.RouteData, context.Controller);

            //Save current HttpContext
            HttpContext oldContext = HttpContext.Current;
            HttpContext.Current = fakeContext;
            if (viewDic == null)
            {
                viewDic = new ViewDataDictionary();
            }
            //Use HtmlHelper to render partial view to fake context 
            HtmlHelper html = new HtmlHelper(new ViewContext(fakeControllerContext,
                new FakeView(), viewDic, new TempDataDictionary(), memWriter),
                new ViewPage());
            html.RenderPartial(viewName, model, viewDic);

            //Restore context 
            HttpContext.Current = oldContext;

            //Flush memory and return output 
            memWriter.Flush();
            return sb.ToString();
        }

        /// <summary>Fake IView implementation, only used to instantiate an HtmlHelper.</summary> 
        public class FakeView : IView
        {
            #region IView Members
            public void Render(ViewContext viewContext, System.IO.TextWriter writer)
            {
                throw new NotImplementedException();
            }
            #endregion
        }
    }
}
